﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OpenLS.Media;
using OpenLS.Spreadsheet.UI.Internals;
using OpenLS.Spreadsheet.UI.Internals.Resources;

namespace OpenLS.Spreadsheet.UI
{
    internal class RowsControl : DimensionsControl
    {
        static RowsControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(RowsControl), new FrameworkPropertyMetadata(typeof(RowsControl)));
        }
        protected override Size MeasureOverride(Size constraint)
        {
            IEnumerable<Row> rows = Rows;
            if (rows == null )
                return new Size(0, 0);
            FormattedText text = new FormattedText("M", CultureInfo.CurrentUICulture, System.Windows.FlowDirection.LeftToRight, GetTypeFace(), FontSize, Brushes.Black);
            var characterCount = Math.Max(Enumerable.Max(Enumerable.Select(Rows, r => r.Label.Length), 3), 3);
            return new Size(text.Width * characterCount + 0, Enumerable.Sum(rows, r => r.ActualHeight));
        }


        protected override void DragDimension(Dimension borderDimension, Vector vector)
        {
            Row column = (Row) borderDimension;
            column.Height = column.ActualHeight + vector.Y;
        }

        protected override void OnMouseDimension(Dimension dimension)
        {

            Row row1 = (Row) dimension;
            Contract.Assert(row1 != null);
            var activeCell = SpreadsheetElement.GetWorkingActiveCell(this);
            int offset = row1.Worksheet.Rows.GetIndexForOffset(/*column1.Offset + */Mouse.GetPosition(Mouse.Captured).Y + this.Fragment.Worksheet.Rows[Fragment.Top].Offset);
            offset = Math.Max(offset, 0);
            Row row2 = row1.Worksheet.Rows[offset];
            var oldValue = SpreadsheetElement.GetWorkingSelection(this);
            if (oldValue is CompositeRange)
            {
                //\\                column2.Worksheet.Selection = CompositeRange.CreateWithLast((CompositeRange) column2.Worksheet.Selection,  new FullColumnRange(column1, column2));
                SpreadsheetElement.SetCurrentRangeForRoot(this, CompositeRange.CreateWithLast((CompositeRange)oldValue,
                    new FullRowRange(row1, row2)), activeCell);
            }
            else
            {
                SpreadsheetElement.SetCurrentRangeForRoot(this, new FullRowRange(row1, row2), activeCell);
                row1.Worksheet.GetPaneFor(row1.Worksheet[row2.Index, 0]).EnsureVisible(new CellAddress(row2.Index, 0));

            }
            //column2.Worksheet.Selection = new FullColumnRange(column1, column2);

        }

        protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
        {
            if (IsEmpty)
                return;
            Point position = e.MouseDevice.GetPosition(this);
            var hit = GetHit(position);
            if (hit == null)
                return;
            Row d = (Row)hit.BorderDimesion;
            if (d != null)
            {
                using (d.Worksheet.Workbook.CreateUndoScope(UIStringTable.AutoFitColumnWidth))
                {
                    foreach (var row in GetRows(d))
                        row.AutoFit();
                }

            }

        }

        static IEnumerable<Row> GetRows(Row row)
        {
            var rowRange = row.Worksheet.Selection as FullRowRange;
            if (rowRange != null && rowRange.Contains(row))
            {
                foreach (var row2 in rowRange.GetRows())
                {
                    yield return row2;
                }
            }
            else
                yield return row;
        }


        protected override Rect GetRect(Dimension dimension)
        {
            Row row = (Row) dimension;
            return new Rect(new Point(0, row.Offset - row.Worksheet.Rows [Fragment.Top].Offset), new Size(ActualWidth, row.ActualHeight));
        }

        protected override DimensionHit GetHit(Point position)
        {
            Dimension d = GetItemAt(position);
            if (d == null)
                return null;
            Rect rect = GetRect(d);
            if (position.Y >= rect.Bottom - tolerance)
            {
                return new DimensionHit(null, d);
            }
            if (position.Y <= rect.Top + tolerance)
            {
                if (d.Index == 0)
                    return new DimensionHit(d, null);
                d = d.Worksheet.Rows[d.Index - 1];
                return new DimensionHit(null, d);
            }
            return new DimensionHit(d, null);
        }

        protected override void FinishDragDimension(Dimension borderDimension)
        {
            Row c = (Row) borderDimension;
            if (!borderDimension.Worksheet.Selection.ContainsRow(c))
                return;
            borderDimension.Worksheet.Selection.SetRowsHeight(c.ActualHeight);
#if DEBUG
            Debug.WriteLine("Setting Row Height");
            for (int i = 0; i < 10; i++)
            {
                Row row = borderDimension.Worksheet.Rows[i];
                Debug.WriteLine(row.Label);
                Debug.WriteLine(row.ActualHeight);
                Debug.WriteLine(row.Height);
                Debug.WriteLine(row.Offset);
            }
#endif
        }

        protected override void SelectDimension(Dimension d, MouseButton argsChangedButton)
        {
            var row = (Row)d;
            var mergeType = GetMergeType();
            var activeCell = SpreadsheetElement.GetWorkingActiveCell(this);
            switch (mergeType)
            {
                case MergeType.Extend:
                    {
                        var range = RangeExtensions.MergeRow(
                            SpreadsheetElement.GetWorkingSelection(this), row, mergeType);
                        SpreadsheetElement.SetCurrentRangeForRoot(this, range, range.FirstCell);
                        /* column.Worksheet.Selection = RangeExtensions.MergeColumn(column.Worksheet.Selection, column,
                          /                                                        mergeType);
                         */
                        //\\);
                        return;
                    }
                case MergeType.Union:
                    {
                        var range = RangeExtensions.MergeRow(
                            SpreadsheetElement.GetWorkingSelection(this),
                            row, mergeType);
                        SpreadsheetElement.SetCurrentRangeForRoot(this,
                                                                  range, range.FirstCell);
                        //\\                                                                             mergeType));
                        //\\                        column.Worksheet.Selection = RangeExtensions.MergeColumn(column.Worksheet.Selection, column,
                        //\\                                                                             mergeType);
                        CaptureDimension(d);
                        return;
                    }
            }
            {
                bool reselect = argsChangedButton != MouseButton.Right;
                if (!reselect)
                {
                    var rr = row.Worksheet.Selection as FullRowRange;
                    if (rr == null)
                        reselect = true;
                    else
                        reselect = !rr.Contains(row);
                }
                if (reselect)
                {
                    EditedCell c = EditionElement.GetEditedCell(this);//\\
                    if (c != null && c.AcceptsPoint)
                    {
                        if (argsChangedButton == MouseButton.Right)
                            return;
                        c._wantsCapture = true;
                        c.Formula.ActivateRowReference(row);
                        return;

                    }
                    SpreadsheetElement.SetCurrentRangeForRoot(this, new FullRowRange(row), row[0]);
                    //column.Worksheet.Selection = new FullColumnRange(column);
                }
                CaptureDimension(d);
            }

        }

        protected override void OnQueryCursor(QueryCursorEventArgs e)
        {
            if (IsEmpty)
                return;

            Point position = e.MouseDevice.GetPosition(this);
            var hit = GetHit(position);
            if (hit == null)
                return;
            if (hit.Dimension != null)
                e.Cursor = OfficeCursors.ArrowRight;
            else
            {
                e.Cursor = OfficeCursors.SizeNS;
            }
        }

        protected IEnumerable<Row> Rows 
        {
            get { return (IEnumerable<Row>) ItemsSource; }
        }
    }
}
